/** sps_service.h - header file for sps_service.cpp
 */

#ifndef __SPS_SERVICE_H__
#define __SPS_SERVICE_H__

#include "sps_config.h"

class SpsService
{
 public:
  SpsService();
  ~SpsService();

  /** @brief Run the service.
   *  @return If no errors, zero is returned. Otherwise, non-zero is returned.
   */
  int runService();

  /** @brief Install the service.
   *  @return If no errors, zero is returned. Otherwise, non-zero is returned.
   */
  int installService();

  /** @brief Uninstall the service.
   *  @return If no errors, zero is returned. Otherwise, non-zero is returned.
   */
  int uninstallService();

  /** @brief Start the service.
   *  @return If no errors, zero is returned. Otherwise, non-zero is returned.
   */
  int startService();

  /** @brief Stop the service.
   *  @return If no errors, zero is returned. Otherwise, non-zero is returned.
   */
  int stopService();

 private:
  static void WINAPI serviceMain(DWORD argc, LPTSTR *args);
  static void WINAPI serviceCtrl(DWORD ctrl);

  /** @brief Get the client ip address.
   *  @param s [in] The socket descriptor.
   *  @return The ip address of the socket.
   */
  static std::string getIpAddress(evutil_socket_t s);

  /** @brief Get mac address of the specific ip address.
   *  @param ip [in] The ip address.
   *  @return The mac address of the specific ip address.
   */
  static std::string getMacAddress(const std::string& ip);

  /** @brief Connect the server using tcp connection.
   *  @param host [in] The server hostname or ip address.
   *  @param serv [in] The server service name or port.
   *  @return If no errors, returns the socket descriptor.
   *   Otherwise, -1 is returned.
   */
  static evutil_socket_t tcpConnect(const char *host, const char *serv);

  /** @brief The connection timer callback function.
   */
  static void connectServer(evutil_socket_t fd, short what, void *args);

  /** @brief The network reading event callback function.
   */
  static void netReadEvent(evutil_socket_t fd, short what, void *args);

  /** @brief Disconnect the connection to server.
   *  @param args [in] The parameters will be used.
   */
  static int disconnectServer(struct _ev_args *args);

  /** @brief Reconnect to server.
   *  @param args [in] The parameters will be used.
   */
  static int reconnectServer(struct _ev_args *args);

  /** @brief Create a database to store sign proxy service information.
   *  @return If no errors, 0 is returned. Otherwise, -1 is returned.
   */
  static int createDatabase();

  /** @brief Destory database.
   *  @return If no errors, 0 is returned. Otherwise, -1 is returned.
   */
  static int destoryDatabase();

  /** @brief Get the communication secret key.
   *  @note The key is stored in sps_priv_key which defined in sps_req.cpp.
   */
  static void getSecretKey();

  /** @brief Whether the service is installed
   *  @return If installed, true is returned. Otherwise, false is returned
   */
  bool isInstalled();

  /** @brief Switch the service status.
   *  @param stop [in] The state of service status.
   *  @return If installed, true is returned. Otherwise, false is returned.
   *  @note If the *stop* is true, switch the service status to SERVICE_STOPPED.
   *   Otherwise, start the service.
   */
  int switchServiceStatus(bool stop);


  static SERVICE_STATUS         status_;
  static SERVICE_STATUS_HANDLE  handle_;
  static struct event_base     *evbase_;
  static std::string            ip_;
  static std::string            mac_;
};

#endif /* __SPS_SERVICE_H__ */
